<?php
// +----------------------------------------------------------------------
// | 有小象汇 自研正版源码 赋能开发者
// +----------------------------------------------------------------------
// | Copyright (c) 2017~2023 http://www.uxphp.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed 有小象汇并不是自由软件，未经许可不能去掉有小象汇相关版权
// +----------------------------------------------------------------------
// | Author:  有小象汇
// +----------------------------------------------------------------------

namespace app\services\car;


use app\dao\car\CarOrderRerentDao;
use app\model\car\CarOccupyTime;
use app\model\car\CarOrder;
use app\model\car\CarOrderRefund;
use app\model\car\CarOrderRerent;
use app\model\car\CarOrderTake;
use app\services\BaseServices;
use crmeb\exceptions\AdminException;
use think\exception\ValidateException;

/**
 * Class CarOrderRerentServices
 * @package app\services\car
 */
class CarOrderRerentServices extends BaseServices
{
    public function __construct(CarOrderRerentDao $dao)
    {
        $this->dao = $dao;
    }

    /**
     * 列表
     * @param array $where
     * @param false $is_page
     * @return array
     */
    public function getList(array $where = [],$is_page = false){
        $page = $limit = 0;
        if($is_page){
            [$page,$limit] = $this->getPageValue();
        }
        $list = $this->dao->getList($where,$page,$limit);
        $status = [-1=>['name'=>'已取消','color'=>'#999999'],0=>['name'=>'未支付','color'=>'default'],10=>['name'=>'申请续租','color'=>'#ff9900'],20=>['name'=>'续租成功','color'=>'#19be6b'],30=>['name'=>'拒绝续租','color'=>'#ed4014']];
        $pay_type = ['weixin'=>['name'=>'微信支付','color'=>'#19be6b'],'yue'=>['name'=>'余额支付','color'=>'#ff9900']];
        foreach ($list['list'] as &$item){
            $differ_day = intval(($item['end_time']-$item['start_time'])/86400);
            $differ_hour = intval(round(($item['end_time']-$item['start_time'])%86400/3600));
            if($differ_day > 0){
                if($differ_hour > 0){
                    $item['duration'] = $differ_day.'天'.$differ_hour.'小时';
                }else{
                    $item['duration'] = $differ_day.'天';
                }
            }else{
                $item['duration'] = $item['book_hour'].'小时';
            }
            $item['status'] = $status[$item['rerent_status']];
            $item['pay_type'] = $item['pay_time'] > 0 ? $pay_type[$item['pay_type']] : ['name'=>'未支付','color'=>'default'];
            $item['start_time'] = $item['start_time'] ? date('Y-m-d H:i',$item['start_time']) : '暂无';
            $item['end_time'] = $item['start_time'] ? date('Y-m-d H:i',$item['end_time']) : '暂无';
            $item['add_time'] = $item['add_time'] ? date('Y-m-d H:i',$item['add_time']) : '暂无';
        }
        return $list;
    }
    /**
     * 续租订单导出
     * @param $where
     * @return mixed
     */
    public function getExportData($where){
        $list = $this->dao->exportOrderRerent($where);
        $status = [
            -1 => '已取消',
            0 => '未支付',
            10 => '申请续租',
            20 => '续租成功',
            30 => '拒绝续租',
        ];
        foreach ($list as &$item){
            $item['add_time'] = $item['add_time'] ? date('Y年m月d日 H时i分', $item['add_time']) : '暂无';
            $item['pay_status'] = $item['pay_time'] ? '已支付' : '未支付';
            $item['start_time'] = $item['start_time'] ? date('m月d日 H时i分', $item['start_time']) : '暂无';
            $item['end_time'] = $item['end_time'] ? date('m月d日 H时i分', $item['end_time']) : '暂无';
            $item['time'] = $item['start_time'].'至'.$item['end_time'];
            $item['rerent_status'] = $status[$item['rerent_status']];
        }
        return $list;
    }

    /**
     * 订单续租
     * @param $data
     * @param $op_user
     * @param $op_user_type
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function createRerent($data,$op_user,$op_user_type){
        $orderInfo = CarOrder::find($data['order_id']);
        $orderInfo = $orderInfo ? $orderInfo->toArray() : [];
        if(!$orderInfo) throw new ValidateException('未查询到订单信息');
        $end_time = strtotime($data['date']);
        $start_time = $orderInfo['end_time'];
        if($start_time > $end_time) throw new ValidateException('续期还车时间需大于原始还车时间');
        // 判断用户的订单是否有其他的续租订单，有看续租时间是否重叠
        $rerent = CarOrderRerent::where(['order_id'=>$data['order_id'],'is_del'=>0,'rerent_status'=>'0|20'])->order('end_time desc')->find();
        $rerent = $rerent ? $rerent->toArray() : [];
        if($rerent){
            if($end_time <= $rerent['end_time']){
                throw new ValidateException('请选择'.date('Y/m/d H:i',$rerent['end_time']).'之后的时间');
            }else{
                $start_time = $rerent['end_time'];
            }
        }
        // 判断用户续租期内车辆有无占用情况
        $car_id = CarOrderTake::where('id',$orderInfo['take_id'])->value('car_id');
        if($car_id){
            if(!$data['is_occupy']){
                /** @var CarOccupyTimeServices $occupyServices */
                $occupyServices = app()->make(CarOccupyTimeServices::class);
                $is_occupy = $occupyServices->isOccupy($car_id,$start_time+1,$end_time,1);
                if($is_occupy) return false; // 询问是否强行续租
            }
        }
        /** @var CarOrderServices $orderServices */
        $orderServices = app()->make(CarOrderServices::class);
        $book_day = intval(($end_time - $start_time) / 86400); // 续租天数
        $book_hour = round(($end_time - $start_time) % 86400 / 3600,2); // 续租小时数
        $car_fee = $orderServices->carFee($orderInfo['type_id'],$start_time,$end_time); // 租车费
        $base_service_fee = $orderServices->baseServiceFee($orderInfo['type_id'],$start_time,$end_time); // 基础服务费
        $service = $orderServices->getcarService($orderInfo['type_id'],$start_time,$end_time); // 获取保险
        $car_service_fee = 0;
        if($orderInfo['car_service_id']){
            foreach ($service as $val){
                if($val['id'] == $orderInfo['car_service_id']){
                    $car_service_fee = $val['price'];
                    break;
                }
            }
        }
        // 续租原价
        $old_price = bcadd($car_fee,$base_service_fee,2);
        $old_price = bcadd($old_price,$car_service_fee,2);
        $insert = [
            'uid'=>$orderInfo['uid'],
            'order_id'=>$data['order_id'],
            'type_id'=>$orderInfo['type_id'],
            'staff_id'=>$op_user['id'],
            'rerent_no'=>$this->getRerentNo(),
            'start_time'=>$start_time,
            'end_time'=>$end_time,
            'book_day'=>$book_day,
            'book_hour'=>$book_hour,
            'car_fee'=>$car_fee,
            'base_service_fee'=>$base_service_fee,
            'car_service_id'=>$orderInfo['car_service_id'] ? $orderInfo['car_service_id'] : '',
            'car_service_name'=>$orderInfo['car_service_name'] ? $orderInfo['car_service_name'] : '',
            'car_service_price'=>$orderInfo['car_service_price'] ? $orderInfo['car_service_price'] : '',
            'car_service_fee'=>$car_service_fee,
            'pay_time'=>0,
            'rerent_status'=>0,
            'refuse_time'=>0,
            'agree_time'=>0,
            'old_price'=>$old_price,
            'rerent_price'=>$old_price,
            'add_time'=>time(),
        ];
        $this->transaction(function () use ($insert,$data,$op_user,$op_user_type,$car_id){
            if($res = CarOrderRerent::insertGetId($insert)){
                if($car_id){
                    $occupy = [
                        'car_id'=>$car_id,
                        'order_id'=>$data['order_id'],
                        'occupy_type'=>'book',
                        'start_time'=>$insert['start_time'],
                        'end_time'=>$insert['end_time'],
                        'remark'=>'订单续租占用',
                        'add_time'=>time(),
                    ];
                    if(!CarOccupyTime::create($occupy)){
                        throw new ValidateException('添加库存占用时间失败');
                    }
                }
                $title = '订单【'.CarOrder::where('id',$data['order_id'])->value('order_no').'】申请续租，续租单号【'.$insert['rerent_no'].'】';
                BaseLogServices::addLog($data['order_id'],2,$title,$op_user_type,$op_user['id'],$op_user['user_name'],6);
            }else{
                throw new ValidateException('续租订单创建失败');
            }
        });
        return true;
    }

    /**
     * 续租单号
     * @return string
     */
    public function getRerentNo(){
        $date = date('YmdHis',time()).rand(10,99);
        return 'XZ'.$date;
    }

    /**
     * 续租详情
     * @param int $rerent_id
     * @return array
     */
    public function getRerentInfo(int $rerent_id){
        $rerentInfo = CarOrderRerent::alias('r')->where('r.id',$rerent_id)
            ->join('user u','u.uid=r.uid','left')
            ->join('car_staff s','s.id=r.staff_id','left')
            ->join('car_order o','o.id=r.order_id','left')
            ->join('car_type t','t.id=o.type_id','left')
            ->join('car_type_info i','i.id=t.type_info_id','left')
            ->join('car_order_take ot','ot.id=o.take_id','left')
            ->field('r.*,s.user_name,s.user_phone,o.order_no,u.nickname,o.type_name,o.type_pic,i.power,i.gear,i.seat_num')
            ->find();
        $rerentInfo = $rerentInfo ? $rerentInfo->toArray() : [];
        if(!$rerentInfo) throw new ValidateException('未查询到该续租订单信息');
        $pay_type = [
            'weixin'=>'微信支付',
            'yue'=>'余额支付',
        ];
        $rerentInfo['gear'] = $rerentInfo['gear'] == 'auto' ? '自动挡':'手动挡';
        $differ_day = intval(($rerentInfo['end_time']-$rerentInfo['start_time'])/86400);
        $differ_hour = intval(round(($rerentInfo['end_time']-$rerentInfo['start_time'])%86400/3600));
        if($differ_day > 0){
            if($differ_hour > 0){
                $rerentInfo['duration'] = $differ_day.'天'.$differ_hour.'小时';
            }else{
                $rerentInfo['duration'] = $differ_day.'天';
            }
        }else{
            $rerentInfo['duration'] = $rerentInfo['book_hour'].'小时';
        }
        $rerentInfo['pay_type'] = $rerentInfo['pay_time'] > 0 ? $pay_type[$rerentInfo['pay_type']] : '未支付';
        $rerentInfo['pay_time'] = $rerentInfo['pay_time'] ? date('Y-m-d H:i:s',$rerentInfo['pay_time']) : '暂无';
        $rerentInfo['start_time'] = $rerentInfo['start_time'] ? date('Y-m-d H:i:s',$rerentInfo['start_time']) : '暂无';
        $rerentInfo['end_time'] = $rerentInfo['end_time'] ? date('Y-m-d H:i:s',$rerentInfo['end_time']) : '暂无';
        $rerentInfo['add_time'] = $rerentInfo['add_time'] ? date('Y-m-d H:i:s',$rerentInfo['add_time']) : '暂无';

        return $rerentInfo;
    }

    /**
     * 取消续租
     * @param int $rerent_id
     * @param $op_user
     * @param $op_user_type
     * @return string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function cancelRerent(int $rerent_id,$op_user,$op_user_type){
        $rerent = CarOrderRerent::where('id',$rerent_id)->find();
        $rerent = $rerent ? $rerent->toArray() : [];
        if(!$rerent) throw new ValidateException('未查询到该续租信息');
        $this->transaction(function () use ($rerent_id,$rerent,$op_user,$op_user_type){
            if(!$res = CarOrderRerent::where('id',$rerent_id)->update(['rerent_status'=>-1,'cancel_time'=>time()])){
                throw new ValidateException('取消失败');
            }
            // 清除对应的库存占用时间
            $occupy = CarOccupyTime::where(['order_id'=>$rerent['order_id'],'start_time'=>$rerent['start_time'],'end_time'=>$rerent['end_time'],'is_del'=>0])
                ->update(['is_del'=>1,'delete_time'=>time()]);
            if($rerent['pay_time'] > 0){ // 已支付，退款
                /** @var CarOrderRefundServices $refundServices */
                $refundServices = app()->make(CarOrderRefundServices::class);
                /** @var CarOrderServices $orderServices */
                $orderServices = app()->make(CarOrderServices::class);
                $orderInfo = CarOrder::find($rerent['order_id']);
                $order_refund = [
                    'order_id'=>$rerent['id'],
                    'uid'=>$rerent['uid'],
                    'refund_no'=>$orderServices->getNewOrderSn('r'),
                    'price'=>$rerent['rerent_price'],
                    'add_time'=>time(),
                    'order_type'=>2,
                ];
                $refund_id = CarOrderRefund::insertGetId($order_refund);
                $refundData = CarOrderRefund::find($refund_id)->toArray();
                $res = $refundServices->payRerentRefund($rerent,$refundData,$op_user,$op_user_type);
            }
            $title = '续租订单【'.$rerent['rerent_no'].'】取消';
            BaseLogServices::addLog($rerent['order_id'],2,$title,$op_user_type,$op_user['id'],$op_user['user_name'],9);
        });
        return '取消成功';
    }
    public function consentApplyFor(array $data,array $op_user,int $op_user_type){
        $rerent = CarOrderRerent::find($data['rerent_id']);
        $rerent = $rerent ? $rerent->toArray() : [];
        if(!$rerent) throw new AdminException('未查询到数据');
        $update = [
            'rerent_status'=>$data['status']
        ];
        if($update['rerent_status'] == 20){
            $update['agree_name'] = $op_user['user_name'];
            $update['agree_time'] = time();
        } else if ($update['rerent_status'] == 30){
            $update['refuse_name'] = $op_user['user_name'];
            $update['refuse_time'] = time();
        }
        $this->transaction(function () use ($data,$rerent,$op_user,$op_user_type,$update){
            if(CarOrderRerent::where('id',$data['rerent_id'])->update($update)){
                if($update['rerent_status'] == 30){
                    $occupy = CarOccupyTime::where(['order_id'=>$rerent['order_id'],'start_time'=>$rerent['start_time'],'end_time'=>$rerent['end_time'],'is_del'=>0])
                        ->update(['is_del'=>1,'delete_time'=>time()]);
//                    if($rerent['pay_time'] > 0){
//                        /** @var CarOrderRefundServices $refundServices */
//                        $refundServices = app()->make(CarOrderRefundServices::class);
//                        /** @var CarOrderServices $orderServices */
//                        $orderServices = app()->make(CarOrderServices::class);
//                        $orderInfo = CarOrder::find($rerent['order_id']);
//                        $order_refund = [
//                            'order_id'=>$rerent['order_id'],
//                            'uid'=>$rerent['uid'],
//                            'refund_no'=>$orderServices->getNewOrderSn('r'),
//                            'price'=>$rerent['rerent_price'],
//                            'add_time'=>time()
//                        ];
//                        $refund_id = CarOrderRefund::insertGetId($order_refund);
//                        $refundData = CarOrderRefund::find($refund_id)->toArray();
//                        $res = $refundServices->payRerentRefund($rerent,$refundData,$op_user,$op_user_type);
//                    }
                }
                if($data['status'] == 20){
                    $tit = '同意续租';
                }else if($data['status'] == 30){
                    $tit = '拒绝续租';
                }else{
                    $tit = '等待确认';
                }
                $title = '续租订单【'.$rerent['rerent_no'].'】'.$tit;
                BaseLogServices::addLog($rerent['order_id'],2,$title,$op_user_type,$op_user['id'],$op_user['user_name'],14);
            }else{
                throw new AdminException('提交失败');
            }
        });
        return '提交成功';
    }
    /**
     * 获取特定时间内订单量
     * @param $time
     * @return int
     */
    public function todayOrderVisit($time){
        return CarOrderRerent::where('pay_time','>',0)->where(['is_del'=>0,'rerent_status'=>20])->whereTime('add_time',$time)->count();
    }

    /**
     * 总销售额
     * @param $time
     * @return float
     */
    public function totalSales($time){
        return CarOrderRerent::whereTime('pay_time',$time)->where(['rerent_status'=>20,'is_del'=>0])->sum('rerent_price');
    }
}
